﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using HtmlAgilityPack;

namespace ChanSharp
{
    public class Thread
    {
        public static WebClient Client { get; set; }
        public List<Post> Posts { get; set; }
        public string URL { get; set; }
        private HtmlDocument document;
        private string rawHTML;

        public bool Ancient
        {
            get
            {
                return rawHTML.Split('\n').Length > 100;
            }
        }

        public Thread(string URL)
        {
            if (Client == null)
            {
                Client = new WebClient();
                Client.Headers.Add("user-agent", "ChanSharp Library (contact cosinemlpg@gmail.com)");
            }

            Posts = new List<Post>();

            this.URL = URL;
        }

        public void DownloadPosts()
        {
            DownloadRaw();
            
            if (Ancient)
            {
                MakeHtmlDocument();
                ParseAncient();
            }
            else
            {
                Strip2012();
                MakeHtmlDocument();
                Parse2012();
            }
        }

        private void DownloadRaw()
        {
            rawHTML = Client.DownloadString(URL);
        }

        private void Strip2012()
        {
            string[] thread = rawHTML.Split('\n');

            //determine which line the <head> ends
            int lineWithBody = 0;
            for (int i = 0; i < thread.Length; i++)
            {
                if (thread[i].StartsWith("</head><body>"))
                {
                    lineWithBody = i;
                    break;
                }
            }

            //copy the remainder into fix
            string[] fix = new string[thread.Length - lineWithBody];
            try { System.Array.Copy(thread, lineWithBody, fix, 0, thread.Length - lineWithBody); }
            catch (Exception ex)
            {
                throw new ChanSharpException("Could not strip away text above </head><body>", ex);
            }

            //remove the first </head>
            int index = fix[0].IndexOf("<body>");
            int length = fix[0].Length - index;
            try { fix[0] = fix[0].Substring(index, length); }
            catch (Exception ex)
            {
                throw new ChanSharpException("Could not remove the first </head>", ex);
            }

            //and last </html>
            int length2 = fix[fix.Length - 1].LastIndexOf("</html>");
            if (length2 != -1)
            {
                try { fix[fix.Length - 1] = fix[fix.Length - 1].Substring(0, length2); }
                catch (Exception ex)
                {
                    throw new ChanSharpException("Could not remove the last </html>", ex);
                }
            }

            //put it back together again and return
            rawHTML = string.Join("\n", fix);
        }

        private void MakeHtmlDocument()
        {
            document = new HtmlAgilityPack.HtmlDocument();
            document.OptionFixNestedTags = true;
            document.LoadHtml(rawHTML);
        }

        private void ParseAncient()
        {
            //TODO: find posts and make them
            throw new NotImplementedException();
        }

        private void Parse2012()
        {
            HtmlNode nodeThread = document.DocumentNode.SelectSingleNode("//div[@class='thread']");
            foreach (HtmlNode nodePost in nodeThread.ChildNodes)
            {
                Post thisPost = null;

                try { thisPost = new Post(nodePost.OuterHtml, false); }
                catch (NullReferenceException ex)
                {
                    Console.WriteLine("fucked up\n\n" + ex.Message + "\n\n" + ex.StackTrace + "\n\n" + nodePost.ToString());
                    continue;
                }

                Posts.Add(thisPost);
            }
        }

        public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
        {
            // Unix timestamp is seconds past epoch
            System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
            return dtDateTime;
        }
    }
}
